package ws
//
//import (
//	"blockchain_data/handler/model"
//	"blockchain_data/middleware"
//	"blockchain_data/utils"
//	"bytes"
//	"compress/flate"
//	"encoding/json"
//	"fmt"
//	"github.com/gorilla/websocket"
//	"github.com/sirupsen/logrus"
//	"io/ioutil"
//	"net/http"
//	"reflect"
//	"time"
//)
//
//
//var log *logrus.Logger
//func init()  {
//	log = middleware.DataLogger()
//}
//type MethonInfo struct {
//	Fun   interface{}
//	Param reflect.Type
//}
//
//func (wsOp *MethonInfo) Init(fun interface{}, param reflect.Type) *MethonInfo {
//	wsOp.Fun = fun
//	wsOp.Param = param
//	return wsOp
//}
//
//type OkWebSocketOp struct {
//	Host string						//根路径
//	Path string						//子路径
//	Conn      *websocket.Conn
//
//	Isclose chan bool
//	Isclose2 chan bool
//	Reconnect chan bool
//
//
//	SubStr []byte
//	Fun    interface{}
//	Param  reflect.Type
//	Methon MethonInfo
//
//	IsPong chan string
//	PingTime time.Duration
//	Heart bool						//是否需要主动发送心跳
//	StopHeart  chan int
//	Ch chan model.Msg
//}
//
//func (wsOp *OkWebSocketOp) Open(path string, host string, heart bool,pingTime time.Duration) bool {
//	wsOp.Host = host
//	wsOp.Path = path
//	wsOp.Heart = heart
//	if(wsOp.Heart){
//		wsOp.PingTime = pingTime
//	}
//
//	wsOp.Reconnect = make(chan bool)
//	wsOp.IsPong = make(chan string)
//	wsOp.Isclose = make(chan bool)
//	wsOp.Isclose2 = make(chan bool)
//	ret := wsOp.ConnServer()
//	return ret
//}
//
//func (wsOp *OkWebSocketOp) Close() {
//	if wsOp.Conn != nil{
//		wsOp.Conn.Close()
//		wsOp.Conn = nil
//		fmt.Println("Close",wsOp.Conn)
//		wsOp.Isclose <- true
//	}
//}
//
//func (wsOp *OkWebSocketOp) ConnServer() bool {
//	url := fmt.Sprintf("wss://%s%s", wsOp.Host, wsOp.Path)
//	fmt.Println(url)
//	var err error
//	wsOp.Conn, _, err = (&websocket.Dialer{
//		Proxy:            http.ProxyFromEnvironment,
//		HandshakeTimeout: 45 * time.Second,
//	}).Dial(url, nil)
//
//	if err != nil {
//		log.Errorf("WebSocket 连接错误: %s", err)
//		time.Sleep(2*time.Second)
//		return false
//	}
//	log.Info("WebSocket 连接成功",string(wsOp.SubStr))
//	wsOp.Conn.SetCloseHandler(wsOp.OnClose)
//
//	if(wsOp.Heart){
//		go wsOp.HeartWork()
//	}else {
//		go wsOp.BaseWork()
//	}
//	go wsOp.ReadLoop()
//	go wsOp.Finalize()
//	return true
//}
//
//func (wsOp *OkWebSocketOp) OnClose(code int, text string) error {
//	log.Info("WebSocket 异常断开，尝试重新连接。。。")
//	wsOp.Conn = nil
//	wsOp.Reconnect <- true
//	return fmt.Errorf("WebSocket 异常断开，尝试重新连接。。。")
//}
//
//// BaseWork 不需要主动发心跳的work
//func (wsOp *OkWebSocketOp)BaseWork()  {
//	for  {
//		select {
//		case <-wsOp.Reconnect:
//			conn := wsOp.ConnServer()
//			time.Sleep(3 * time.Second)
//			if(!conn){
//				//两秒后重连
//				if len(wsOp.Reconnect) == 0 {
//					wsOp.Reconnect <- true
//				}
//			}else {
//				wsOp.Sub(wsOp.SubStr,wsOp.Fun,wsOp.Param)
//			}
//			return
//		}
//	}
//}
//
//// HeartWork 需要主动发心跳的work
//func (wsOp *OkWebSocketOp)HeartWork()  {
//	//每20秒发一次ping
//	ticker := time.NewTicker(wsOp.PingTime)
//	defer ticker.Stop()
//	for {
//		select {
//		case <-ticker.C:
//			if wsOp.Conn != nil{
//				wsOp.Ping()
//			}
//		case <-wsOp.Reconnect:
//			wsOp.IsPong <- "pong"
//			conn := wsOp.ConnServer()
//			time.Sleep(3 * time.Second)
//			log.Info("HeartWork，连接",conn)
//			if(!conn){
//				//两秒后重连
//				if len(wsOp.Reconnect) == 0 {
//					wsOp.Reconnect <- true
//				}
//			}else {
//				log.Info("HeartWork，订阅",conn)
//				wsOp.Sub(wsOp.SubStr,wsOp.Fun,wsOp.Param)
//			}
//			return
//		case <-wsOp.Isclose2:
//			return
//		}
//	}
//}
//
//// Finalize 结束需要检查通道是否都关闭
//func (wsOp *OkWebSocketOp) Finalize()  {
//	defer func() {
//		log.Info("关闭订阅的连接",string(wsOp.SubStr))
//	}()
//	for{
//		select {
//		case <-wsOp.Isclose:
//			close(wsOp.Isclose)
//			close(wsOp.Isclose2)
//			close(wsOp.Reconnect)
//			return
//		}
//	}
//}
//
//// Ping 如果有需要主动发送心跳重写
//func (wsOp *OkWebSocketOp) Ping()  {
//	msg := "ping"
//	//log.Printf("Send Msg: %s", msg)
//	if wsOp.Conn != nil {
//		wsOp.Conn.WriteMessage(websocket.TextMessage, []byte(msg))
//		go wsOp.Pong()
//	}
//}
//
//// Pong 响应
//func (wsOp *OkWebSocketOp) Pong()  {
//	//如果20秒内没有pong就重新连接
//	ticker := time.NewTicker(wsOp.PingTime)
//	defer ticker.Stop()
//	select {
//	case <-ticker.C:
//		log.Error("pong主动重连",string(wsOp.SubStr))
//		if wsOp.Conn != nil{
//			wsOp.Conn.Close()
//			wsOp.Conn = nil
//		}
//		if len(wsOp.Reconnect) == 0{
//			wsOp.Reconnect <- true
//		}
//	case <-wsOp.IsPong:
//		return
//	}
//}
//
//func (wsOp *OkWebSocketOp) ReadLoop() {
//	for wsOp.Conn != nil{
//		messageType, message, err := wsOp.Conn.ReadMessage()
//		if err != nil && wsOp.Conn != nil{
//			fmt.Println(wsOp.Conn)
//			log.Errorf("数据获取异常: %s", err)
//			fmt.Println(len(wsOp.Reconnect))
//			if len(wsOp.Reconnect) == 0{
//				wsOp.Reconnect <- true
//			}
//			return
//		}
//		txtMsg := message
//		switch messageType {
//		case websocket.TextMessage:
//		case websocket.BinaryMessage:
//			txtMsg, err = wsOp.GzipDecode(message)
//		}
//		var jdata map[string]interface{}
//		if string(txtMsg) == "pong" {
//			pong := wsOp.IsPong
//			pong <- "pong"
//		}else {
//			err = json.Unmarshal([]byte(message), &jdata)
//			if err != nil {
//				log.Errorf("msg to map[string]json.RawMessage error: %s", err)
//				continue
//			}
//			if _, found := jdata["data"]; found{
//				wsOp.HandleSubCallbackFun(string(txtMsg))
//			}else {
//				myMsg := &model.Msg{}
//				err = utils.JsonBytes2Struct(txtMsg, myMsg)
//				if err == nil {
//					if myMsg.Event != "error"{
//						wsOp.Ch <- model.Msg{Event: "success",Msg: "订阅成功"}
//						//记录信息
//						log.Info(string(message))
//					}else {
//						wsOp.Ch <- model.Msg{Event: "error",Msg: "订阅失败"}
//						//记录信息
//						log.Errorf(string(message))
//					}
//				}else {
//					wsOp.Ch <- model.Msg{Event: "error",Msg: "订阅失败"}
//					log.Errorf(string(message))
//				}
//			}
//		}
//
//
//	}
//}
//
//func (wsOp *OkWebSocketOp) HandleSubCallbackFun(data string) {
//	var mi *MethonInfo = nil
//	mi = new(MethonInfo).Init(wsOp.Fun, wsOp.Param)
//
//	wsOp.RunFunction(mi, data)
//}
//
//func (wsOp *OkWebSocketOp) RunFunction(mi *MethonInfo, data string) {
//	param := reflect.New(mi.Param).Interface()
//	json.Unmarshal([]byte(data), &param)
//
//	rargs := make([]reflect.Value, 1)
//
//	rargs[0] = reflect.ValueOf(param)
//	fun := reflect.ValueOf(mi.Fun)
//	fun.Call(rargs)
//}
//
//func (wsOp *OkWebSocketOp) Sub(subStr []byte, fun interface{}, param reflect.Type) bool {
//	wsOp.SubStr = subStr
//	wsOp.Fun = fun
//	wsOp.Param = param
//	err := wsOp.Conn.WriteMessage(websocket.TextMessage, subStr)
//	if err != nil{
//		log.Error(err)
//	}
//
//	return true
//}
//
//func (wsOp *OkWebSocketOp) Unsub(unsubStr []byte) bool {
//	wsOp.Conn.WriteMessage(websocket.TextMessage, unsubStr)
//	return true
//}
//
//func (wsOp *OkWebSocketOp) GzipDecode(in []byte) ([]byte, error) {
//	reader := flate.NewReader(bytes.NewReader(in))
//	defer reader.Close()
//
//	return ioutil.ReadAll(reader)
//}
//
